package term // import "xemo.top/docker/docker/pkg/term"
import (
	"github.com/Azure/go-ansiterm/winterm"
	"io"
	"os"
	"syscall"
	windowsconsole "xemo.top/docker/docker/pkg/term/windows"
)

// 状态保持终端的控制台模式
// State holds the console mode for the terminal
type State struct {
	mode uint32
}

// Winsize is used for window size.
type Winsize struct {
	Height uint16
	Width  uint16
}

// GetWinsize 返回基于指定文件描述符的窗口大小
// GetWinsize returns the window size based on the specified file descriptor
func GetWinsize(fd uintptr) (*Winsize, error) {
	info, err := winterm.GetConsoleScreenBufferInfo(fd)
	if err != nil {
		return nil, err
	}
	winsize := &Winsize{
		Width:  uint16(info.Window.Right - info.Window.Left + 1),
		Height: uint16(info.Window.Bottom - info.Window.Top + 1),
	}
	return winsize, nil
}

// vtInputSupported is true if winter.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console
var vtInputSupported bool

// StdStreams 返回标准流 (stdin，stdout，stderr)。
// StdStreams returns the standard streams (stdin,stdout,stderr).
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
	// 如果可能，请在所有std句柄上打开VT处理。这可能会失败，在这种情况下将回退到终端仿真。
	// Turn on VT handling on all std handles, if possible.This might fail,in which case will fall back to terminal emulation.
	var emulateStdin, emulateStdout, emulateStderr bool
	fd := os.Stdin.Fd()
	if mode, err := winterm.GetConsoleMode(fd); err == nil {
		// 验证是否支持winterm.Enable_ virtual_terminal_input，但不设置它。
		// Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported,but do not set it.
		if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
			emulateStdin = true
		} else {
			vtInputSupported = true
		}
		// 在失败时无条件地将控制台模式设置回，因为SetConsoleMode记住输入句柄上的无效位。
		// Unconditionally set the console mode back on failure because SetConsoleMode remembers invalid bits on input handles.
		winterm.SetConsoleMode(fd, mode)
	}
	fd = os.Stdout.Fd()
	if mode, err := winterm.GetConsoleMode(fd); err == nil {
		// 验证支持的winterm.Disable_ newline_auto_return，但不设置它
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported,but do not set it
		if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStdout = true
		} else {
			winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}
	fd = os.Stderr.Fd()
	if mode, err := winterm.GetConsoleMode(fd); err == nil {
		// 验证winterm。支持DISABLE_NEWLINE_AUTO_RETURN，但不要设置它。
		// Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported,but do not set it.
		if err = winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING|winterm.DISABLE_NEWLINE_AUTO_RETURN); err != nil {
			emulateStderr = true
		} else {
			winterm.SetConsoleMode(fd, mode|winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
		}
	}
	if emulateStdin {
		stdIn = windowsconsole.NewAnsiReader(syscall.STD_INPUT_HANDLE)
	} else {
		stdIn = os.Stdin
	}
	if emulateStdout {
		stdOut = windowsconsole.NewAnsiWriter(syscall.STD_INPUT_HANDLE)
	} else {
		stdOut = os.Stdout
	}
	if emulateStderr {
		stdErr = windowsconsole.NewAnsiWriter(syscall.STD_ERROR_HANDLE)
	} else {
		stdErr = os.Stderr
	}
	return
}
